/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>

#include <internal/bus/bus_i2c_mux/i2c_mux.h>
#include <internal/hasdef.h>
#include <mc/dict.h>

namespace {

class bus_i2c_mux_test : public ::testing::Test {
protected:
    dev::bus_i2c_mux m_bus;
};

// 校验初始化流程能够读取 ChannelId
TEST_F(bus_i2c_mux_test, init_with_channel_id) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<uint8_t>(5);

    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(5));
}

// 未提供 ChannelId 时应保持默认值
TEST_F(bus_i2c_mux_test, init_without_channel_id) {
    mc::mutable_dict csr_object;
    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(0));
}

// 无法转换的 ChannelId 应导致初始化失败
TEST_F(bus_i2c_mux_test, init_with_invalid_channel_id) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = std::string("invalid");

    EXPECT_FALSE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(0));
}

// read 接口当前不支持，期望抛出异常
TEST_F(bus_i2c_mux_test, read_not_supported) {
    ACCESS_DATA_S data{};
    EXPECT_THROW(m_bus.read(data), mc::invalid_op_exception);
}

// write 接口当前不支持，期望抛出异常
TEST_F(bus_i2c_mux_test, write_not_supported) {
    ACCESS_DATA_S data{};
    EXPECT_THROW(m_bus.write(data), mc::invalid_op_exception);
}

// 锁接口不支持，需抛出异常
TEST_F(bus_i2c_mux_test, lock_not_supported) {
    EXPECT_THROW(m_bus.bus_lock(), mc::invalid_op_exception);
    EXPECT_THROW(m_bus.bus_unlock(), mc::invalid_op_exception);
}

// 测试 ChannelId 边界值：最小值 0
TEST_F(bus_i2c_mux_test, init_with_channel_id_min) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<uint8_t>(0);

    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(0));
}

// 测试 ChannelId 边界值：最大值 255
TEST_F(bus_i2c_mux_test, init_with_channel_id_max) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<uint8_t>(255);

    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(255));
}

// 测试 ChannelId 为 int32_t 类型但可以转换为 uint8_t
TEST_F(bus_i2c_mux_test, init_with_channel_id_int32) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<int32_t>(100);

    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(100));
}

// 测试 ChannelId 为 uint16_t 类型但可以转换为 uint8_t
TEST_F(bus_i2c_mux_test, init_with_channel_id_uint16) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<uint16_t>(200);

    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(200));
}

// 测试 ChannelId 为 double 类型，无法转换应导致初始化失败
TEST_F(bus_i2c_mux_test, init_with_channel_id_double) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = 3.14;
    // 只测试是否崩溃
    m_bus.init(csr_object);
}

// 测试 ChannelId 为 bool 类型，无法转换应导致初始化失败
TEST_F(bus_i2c_mux_test, init_with_channel_id_bool) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = true;

    // 只测试是否崩溃
    m_bus.init(csr_object);
}

// 测试多次调用 init，验证状态会被覆盖
TEST_F(bus_i2c_mux_test, init_multiple_times) {
    mc::mutable_dict csr_object1;
    csr_object1["ChannelId"] = static_cast<uint8_t>(10);
    EXPECT_TRUE(m_bus.init(csr_object1));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(10));

    mc::mutable_dict csr_object2;
    csr_object2["ChannelId"] = static_cast<uint8_t>(20);
    EXPECT_TRUE(m_bus.init(csr_object2));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(20));

    mc::mutable_dict csr_object3;
    EXPECT_TRUE(m_bus.init(csr_object3));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(20)); // 保持上次的值
}

// 测试多次调用 get_id，验证返回值一致性
TEST_F(bus_i2c_mux_test, get_id_consistency) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<uint8_t>(42);
    EXPECT_TRUE(m_bus.init(csr_object));

    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(42));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(42));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(42));
}

// 测试 read 异常消息
TEST_F(bus_i2c_mux_test, read_exception_message) {
    ACCESS_DATA_S data{};
    try {
        m_bus.read(data);
        FAIL() << "Expected exception was not thrown";
    } catch (const mc::invalid_op_exception& e) {
        EXPECT_NE(std::string(e.what()).find("I2C MUX read not supported"), std::string::npos);
    }
}

// 测试 write 异常消息
TEST_F(bus_i2c_mux_test, write_exception_message) {
    ACCESS_DATA_S data{};
    try {
        m_bus.write(data);
        FAIL() << "Expected exception was not thrown";
    } catch (const mc::invalid_op_exception& e) {
        EXPECT_NE(std::string(e.what()).find("I2C MUX write not supported"), std::string::npos);
    }
}

// 测试 bus_lock 异常消息
TEST_F(bus_i2c_mux_test, bus_lock_exception_message) {
    try {
        m_bus.bus_lock();
        FAIL() << "Expected exception was not thrown";
    } catch (const mc::invalid_op_exception& e) {
        EXPECT_NE(std::string(e.what()).find("I2C MUX bus_lock not supported"), std::string::npos);
    }
}

// 测试 bus_unlock 异常消息
TEST_F(bus_i2c_mux_test, bus_unlock_exception_message) {
    try {
        m_bus.bus_unlock();
        FAIL() << "Expected exception was not thrown";
    } catch (const mc::invalid_op_exception& e) {
        EXPECT_NE(std::string(e.what()).find("I2C MUX bus_unlock not supported"), std::string::npos);
    }
}

// 测试 read 返回类型（虽然会抛异常，但验证函数签名）
TEST_F(bus_i2c_mux_test, read_return_type) {
    ACCESS_DATA_S data{};
    EXPECT_THROW(
        {
            uint32_t result = m_bus.read(data);
            (void)result; // 避免未使用变量警告
        },
        mc::invalid_op_exception);
}

// 测试 write 返回类型（虽然会抛异常，但验证函数签名）
TEST_F(bus_i2c_mux_test, write_return_type) {
    ACCESS_DATA_S data{};
    EXPECT_THROW(
        {
            uint32_t result = m_bus.write(data);
            (void)result; // 避免未使用变量警告
        },
        mc::invalid_op_exception);
}

// 测试初始化后 ChannelId 为空字典的情况
TEST_F(bus_i2c_mux_test, init_with_empty_dict) {
    mc::mutable_dict csr_object;
    EXPECT_TRUE(m_bus.init(csr_object));
    EXPECT_EQ(m_bus.get_id(), static_cast<uint8_t>(0));
}

// 测试 ChannelId 为负数（int32_t），应导致转换失败
TEST_F(bus_i2c_mux_test, init_with_channel_id_negative) {
    mc::mutable_dict csr_object;
    csr_object["ChannelId"] = static_cast<int32_t>(-1);

    // 只测试是否崩溃
    m_bus.init(csr_object);
}

} // namespace
